package com.aspire.nm.component.cmppserver.filter;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.annotation.Resource;

import org.apache.mina.core.filterchain.IoFilterAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.firewall.Subnet;
import org.springframework.stereotype.Service;

import com.aspire.nm.component.cmppserver.runTime.SysRunTimeService;
import com.aspire.nm.component.cmppserver.util.LogService;

@Service
public class AdressFilter extends IoFilterAdapter {
	
	@Resource
	private LogService logService;
	@Resource
	private SysRunTimeService sysRunTimeService;
	
	private List<Subnet> blackList = new CopyOnWriteArrayList<Subnet>();

    public void add(InetAddress address) {
        if (address == null) {
            throw new IllegalArgumentException("Adress to block can not be null");
        }
        blackList.add(new Subnet(address, 32));
    }
    public void remove(InetAddress address) {
        if (address == null) {
            throw new IllegalArgumentException("Adress to unblock can not be null");
        }
        blackList.remove(new Subnet(address, 32));
    }

    
    
    
    
    
    
    
    
    
    
    

    @Override
    public void sessionCreated(NextFilter nextFilter, IoSession session) {
        if (!isBlack(session)) {
            nextFilter.sessionCreated(session);
        } else {
        	sysRunTimeService.getForBiddenIpCount().increment();
        	logService.refuseIp(session);
        	session.close(true);
        }
    }
    @Override
    public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
    	if (!isBlack(session)) {
            nextFilter.sessionOpened(session);
        } 
    }
    @Override
    public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
    	if (!isBlack(session)) {
            nextFilter.sessionClosed(session);
        }
    }
    
    
    private boolean isBlack(IoSession session) {
        SocketAddress remoteAddress = session.getRemoteAddress();
        if (remoteAddress instanceof InetSocketAddress) {
            InetAddress address = ((InetSocketAddress) remoteAddress).getAddress();
            for (Subnet subnet : blackList) {
                if (subnet.inSubnet(address)) {
                    return true;
                }
            }
        }
        return false;
    }
}

